<template>
  <div class="visualization-container">
    <el-card class="filter-card">
      <template #header>
        <div class="card-header">
          <h2>可视化分析</h2>
        </div>
      </template>

      <el-form :model="filterForm" label-width="100px" class="filter-form">
        <el-row :gutter="20">
          <el-col :span="8">
            <el-form-item label="选择课程">
              <el-select
                v-model="filterForm.courseId"
                placeholder="请选择课程"
                style="width: 100%"
                @change="handleCourseChange"
              >
                <el-option
                  v-for="course in courses"
                  :key="course.id"
                  :label="course.name"
                  :value="course.id"
                />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item label="选择班级">
              <el-select
                v-model="filterForm.classId"
                placeholder="请选择班级"
                style="width: 100%"
                :disabled="!filterForm.courseId"
              >
                <el-option
                  v-for="classItem in filteredClasses"
                  :key="classItem.id"
                  :label="classItem.name"
                  :value="classItem.id"
                />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item label="报告目录">
              <el-input
                v-model="filterForm.reportDirectory"
                placeholder="请输入实验报告目录路径"
              >
                <template #append>
                  <el-button @click="showDirectorySelector = true">
                    选择目录
                  </el-button>
                </template>
              </el-input>

              <!-- 文件系统目录选择器组件 -->
              <file-system-directory-selector
                v-model="showDirectorySelector"
                :initial-path="filterForm.reportDirectory"
                @select="handleDirectorySelected"
                @cancel="showDirectorySelector = false"
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="图表类型">
              <el-select v-model="chartType" placeholder="请选择图表类型" style="width: 100%" @change="onChartTypeChange">
                <el-option label="折线图" value="line" />
                <el-option label="柱状图" value="bar" />
                <el-option label="饼图" value="pie" />
                <el-option label="雷达图" value="radar" />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="6">
            <el-form-item label="主题颜色">
              <el-color-picker v-model="chartColor" show-alpha @change="onColorChange" />
            </el-form-item>
          </el-col>
          <el-col :span="6">
            <el-form-item label="折线样式">
              <el-select v-model="lineStyle" placeholder="请选择折线样式" style="width: 100%" @change="onLineStyleChange">
                <el-option label="直线" value="straight" />
                <el-option label="平滑曲线" value="smooth" />
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-form-item>
          <el-button type="primary" @click="analyzeReports" :loading="analyzing">
            生成图表
          </el-button>
          <el-dropdown @command="handleExportCommand" style="margin-left: 10px;">
            <el-button type="success" :disabled="!chartRendered">
              导出图表 <el-icon class="el-icon--right"><arrow-down /></el-icon>
            </el-button>
            <template #dropdown>
              <el-dropdown-menu>
                <el-dropdown-item command="png">导出为PNG图片</el-dropdown-item>
                <el-dropdown-item command="jpeg">导出为JPEG图片</el-dropdown-item>
                <el-dropdown-item command="svg">导出为SVG矢量图</el-dropdown-item>
                <el-dropdown-item command="pdf">导出为PDF文档</el-dropdown-item>
              </el-dropdown-menu>
            </template>
          </el-dropdown>
        </el-form-item>
      </el-form>
    </el-card>

    <!-- 图表预览区域 -->
    <el-card class="chart-card">
      <template #header>
        <div class="card-header">
          <h3>实验报告提交率分析</h3>
          <div class="chart-actions" v-if="chartRendered">
            <el-button-group>
              <el-button size="small" @click="toggleDataTable">
                {{ showDataTable ? '隐藏数据表' : '显示数据表' }}
              </el-button>
              <el-button size="small" @click="refreshChart">
                <el-icon><refresh /></el-icon> 刷新图表
              </el-button>
              <el-button size="small" type="primary" @click="exportChart">
                <el-icon><download /></el-icon> 导出图表
              </el-button>
            </el-button-group>
          </div>
        </div>
      </template>

      <!-- 图表容器区域 -->
      <div class="chart-area">
        <!-- 图表容器始终存在，但根据状态显示或隐藏 -->
        <div ref="chartContainer" class="chart-container"></div>

        <!-- 未渲染时显示的占位符 -->
        <div v-if="!chartRendered" class="chart-placeholder">
          <el-empty description="请选择课程、班级和报告目录，然后点击生成图表按钮">
            <template #image>
              <el-icon class="empty-icon"><data-analysis /></el-icon>
            </template>
            <el-button type="primary" @click="analyzeReports" :loading="analyzing" :disabled="!filterForm.courseId || !filterForm.classId || !filterForm.reportDirectory">
              生成图表
            </el-button>
          </el-empty>
        </div>

        <el-collapse-transition>
          <div v-if="showDataTable && chartRendered" class="data-table-container">
            <h4>实验报告提交率数据表</h4>
            <el-table :data="chartData" border style="width: 100%">
              <el-table-column prop="experimentName" label="实验名称" />
              <el-table-column prop="submissionRate" label="提交率">
                <template #default="scope">
                  {{ (scope.row.submissionRate * 100).toFixed(2) }}%
                </template>
              </el-table-column>
              <el-table-column prop="submittedCount" label="已交人数" />
              <el-table-column prop="totalStudents" label="总人数" />
            </el-table>
          </div>
        </el-collapse-transition>
      </div>
    </el-card>
  </div>
</template>

<script>
import { ref, computed, onMounted, nextTick } from 'vue'
import { useStore } from 'vuex'
import { ElMessage } from 'element-plus'
import * as echarts from 'echarts'
import { ArrowDown, Refresh, Download, DataAnalysis } from '@element-plus/icons-vue'
import FileSystemDirectorySelector from '@/components/FileSystemDirectorySelector.vue'
import logger from '@/utils/Logger'
import { saveAs } from 'file-saver'
import html2canvas from 'html2canvas'
import jsPDF from 'jspdf'

export default {
  name: 'VisualizationChart',
  components: {
    ArrowDown,
    Refresh,
    Download,
    DataAnalysis,
    FileSystemDirectorySelector
  },
  setup() {
    const store = useStore()
    const chartContainer = ref(null)
    let chart = null

    // 状态
    const filterForm = ref({
      courseId: '',
      classId: '',
      reportDirectory: ''
    })
    const analyzing = ref(false)
    const chartRendered = ref(false)
    const experimentResults = ref([])
    const chartType = ref('line')
    const chartColor = ref('#409EFF')
    const lineStyle = ref('straight') // 默认使用直线
    const showDataTable = ref(false)
    const chartData = ref([])
    const chartOptions = ref({})
    const showDirectorySelector = ref(false)

    // 计算属性
    const courses = computed(() => {
      return store.getters.getCourses
    })

    const classes = computed(() => {
      return store.getters.getClasses
    })

    const filteredClasses = computed(() => {
      if (!filterForm.value.courseId) {
        return []
      }
      return classes.value.filter(c => c.courseId === filterForm.value.courseId)
    })

    // 方法
    const loadData = async () => {
      try {
        // 从后端API获取课程和班级数据
        await store.dispatch('fetchCourses')
        await store.dispatch('fetchClasses')

        logger.info('课程和班级数据加载成功')
      } catch (error) {
        logger.error('加载数据失败', error)
        ElMessage.error('加载数据失败')
      }
    }

    const handleCourseChange = () => {
      // 切换课程时重置班级选择
      filterForm.value.classId = ''
    }

    // 打开目录选择器对话框
    const handleSelectDirectory = async () => {
      console.log('VisualizationChart: 打开目录选择器对话框');
      showDirectorySelector.value = true;
      console.log('VisualizationChart: showDirectorySelector =', showDirectorySelector.value);
    }

    // 处理目录选择
    const handleDirectorySelected = (path) => {
      console.log('VisualizationChart: 目录选择回调被触发，path =', path);
      if (path) {
        filterForm.value.reportDirectory = path;
        ElMessage.success('已选择目录: ' + path);
        logger.info('目录选择成功', { path });
      }
      showDirectorySelector.value = false;
      console.log('VisualizationChart: 目录选择完成，showDirectorySelector =', showDirectorySelector.value);
    }

    const analyzeReports = async () => {
      if (!filterForm.value.courseId || !filterForm.value.classId || !filterForm.value.reportDirectory) {
        ElMessage.warning('请选择课程、班级和实验报告目录')
        return
      }

      analyzing.value = true
      try {
        // 获取选中的课程和班级
        const selectedCourse = courses.value.find(c => c.id === filterForm.value.courseId)
        const selectedClass = classes.value.find(c => c.id === filterForm.value.classId)

        if (!selectedCourse || !selectedClass) {
          throw new Error('未找到选中的课程或班级')
        }

        // 调用后端API获取学生数据
        await store.dispatch('fetchStudentsByClass', selectedClass.id)

        // 调用后端API获取实验数据
        await store.dispatch('fetchExperimentsByCourse', selectedCourse.id)

        // 调用后端API分析报告
        const analysisResult = await store.dispatch('scanAndAnalyzeReports', {
          classId: selectedClass.id,
          courseId: selectedCourse.id,
          directoryPath: filterForm.value.reportDirectory
        })

        // 处理分析结果
        if (analysisResult && analysisResult.experimentStatistics) {
          experimentResults.value = analysisResult.experimentStatistics.map(stat => ({
            experimentName: stat.experimentName,
            totalStudents: stat.totalStudents,
            submittedCount: stat.submittedCount,
            missingCount: stat.missingCount,
            submissionRate: stat.submissionRate,
            missingStudents: stat.missingStudents || []
          }))

          logger.info('实验报告分析完成', {
            courseId: selectedCourse.id,
            classId: selectedClass.id,
            experimentsCount: experimentResults.value.length
          })

          // 确保有实验数据
          if (experimentResults.value.length > 0) {
            // 渲染图表
            await renderChart()
          } else {
            ElMessage.warning('没有找到实验数据，无法生成图表')
          }
        } else {
          ElMessage.warning('分析结果为空，请检查报告目录是否正确')
        }
      } catch (error) {
        logger.error('分析实验报告失败', error)
        ElMessage.error(`分析实验报告失败: ${error.message}`)
      } finally {
        analyzing.value = false
      }
    }

    const renderChart = async () => {
      // 确保有数据可以渲染
      if (experimentResults.value.length === 0) {
        logger.warn('没有数据可以渲染图表')
        return
      }

      // 先设置渲染标志，确保容器可见
      chartRendered.value = true

      // 等待DOM更新完成
      await nextTick()
      await new Promise(resolve => setTimeout(resolve, 100)) // 额外等待100ms确保DOM已更新

      // 确保图表容器存在
      if (!chartContainer.value) {
        logger.error('图表容器不存在')
        ElMessage.error('图表容器不存在，无法渲染图表')
        return
      }

      try {
        logger.info('开始渲染图表', {
          containerExists: !!chartContainer.value,
          containerWidth: chartContainer.value?.clientWidth,
          containerHeight: chartContainer.value?.clientHeight
        })

        // 销毁旧图表
        if (chart) {
          chart.dispose()
        }

        // 创建新图表
        chart = echarts.init(chartContainer.value)

        // 准备数据
        const xAxisData = experimentResults.value.map(result => result.experimentName)
        const submissionRates = experimentResults.value.map(result => parseFloat((result.submissionRate * 100).toFixed(2)))

        // 更新图表数据
        chartData.value = experimentResults.value.map(result => ({
          experimentName: result.experimentName,
          submissionRate: result.submissionRate,
          submittedCount: result.submittedCount,
          totalStudents: result.totalStudents
        }))

        logger.info('图表数据准备完成', {
          xAxisData,
          submissionRates,
          chartType: chartType.value
        })

      // 基础配置
      const baseOption = {
        title: {
          text: '实验报告提交率分析',
          subtext: '横轴为实验编号，纵轴为提交率（提交人数/总人数）',
          left: 'center',
          top: 10,
          textStyle: {
            fontSize: 18,
            fontWeight: 'bold'
          },
          subtextStyle: {
            fontSize: 12
          }
        },
        tooltip: {
          trigger: 'axis',
          formatter: function(params) {
            const param = params[0];
            return `${param.name}<br/>${param.seriesName}: ${param.value}%<br/>提交人数: ${experimentResults.value[param.dataIndex].submittedCount}<br/>总人数: ${experimentResults.value[param.dataIndex].totalStudents}`;
          },
          axisPointer: {
            type: 'cross',
            label: {
              backgroundColor: '#6a7985'
            }
          }
        },
        legend: {
          data: ['提交率'],
          bottom: 10
        },
        toolbox: {
          show: true,
          feature: {
            dataZoom: {
              yAxisIndex: 'none'
            },
            dataView: { readOnly: false },
            magicType: { type: ['line', 'bar'] },
            restore: {},
            saveAsImage: {}
          },
          right: 20,
          top: 20
        },
        grid: {
          left: '5%',
          right: '5%',
          bottom: '15%',
          top: '20%',
          containLabel: true
        }
      }

      // 根据图表类型设置不同的选项
      let specificOption = {}

      switch (chartType.value) {
        case 'line':
          specificOption = {
            xAxis: {
              type: 'category',
              data: xAxisData,
              name: '实验编号',
              nameLocation: 'middle',
              nameGap: 30,
              axisLabel: {
                rotate: 45,
                formatter: function(value) {
                  // 确保显示"实验X"格式
                  if (value.includes('实验')) {
                    return value;
                  } else {
                    return '实验' + value;
                  }
                }
              }
            },
            yAxis: {
              type: 'value',
              min: 0,
              max: 100,
              name: '提交率(%)',
              nameLocation: 'middle',
              nameGap: 50,
              axisLabel: {
                formatter: '{value}%'
              }
            },
            series: [
              {
                name: '提交率',
                type: 'line',
                data: submissionRates,
                markLine: {
                  data: [
                    {
                      type: 'average',
                      name: '平均值'
                    }
                  ]
                },
                markPoint: {
                  data: [
                    { type: 'max', name: '最高提交率' },
                    { type: 'min', name: '最低提交率' }
                  ]
                },
                label: {
                  show: true,
                  position: 'top',
                  formatter: '{c}%'
                },
                itemStyle: {
                  color: chartColor.value
                },
                lineStyle: {
                  width: 3,
                  type: 'solid'
                },
                smooth: lineStyle.value === 'smooth' // 根据用户选择决定是否使用平滑曲线
              }
            ]
          }
          break

        case 'bar':
          specificOption = {
            xAxis: {
              type: 'category',
              data: xAxisData,
              axisLabel: {
                rotate: 45
              }
            },
            yAxis: {
              type: 'value',
              min: 0,
              max: 100,
              axisLabel: {
                formatter: '{value}%'
              }
            },
            series: [
              {
                name: '提交率',
                type: 'bar',
                data: submissionRates,
                markLine: {
                  data: [
                    {
                      type: 'average',
                      name: '平均值'
                    }
                  ]
                },
                itemStyle: {
                  color: chartColor.value
                }
              }
            ]
          }
          break

        case 'pie':
          specificOption = {
            tooltip: {
              trigger: 'item',
              formatter: '{b}: {c}%'
            },
            legend: {
              orient: 'vertical',
              left: 'left',
              data: xAxisData
            },
            series: [
              {
                name: '提交率',
                type: 'pie',
                radius: '60%',
                center: ['50%', '60%'],
                data: xAxisData.map((name, index) => ({
                  name,
                  value: submissionRates[index]
                })),
                itemStyle: {
                  emphasis: {
                    shadowBlur: 10,
                    shadowOffsetX: 0,
                    shadowColor: 'rgba(0, 0, 0, 0.5)'
                  }
                },
                label: {
                  formatter: '{b}: {c}%'
                }
              }
            ]
          }
          break

        case 'radar':
          specificOption = {
            tooltip: {
              trigger: 'item'
            },
            radar: {
              indicator: xAxisData.map(name => ({
                name,
                max: 100
              }))
            },
            series: [
              {
                name: '提交率',
                type: 'radar',
                data: [
                  {
                    value: submissionRates,
                    name: '提交率',
                    itemStyle: {
                      color: chartColor.value
                    },
                    areaStyle: {
                      color: chartColor.value,
                      opacity: 0.3
                    }
                  }
                ]
              }
            ]
          }
          break
      }

      // 合并选项
      const option = { ...baseOption, ...specificOption }
      chartOptions.value = option

      // 渲染图表
      chart.setOption(option)

      // 确保图表正确渲染
      chart.resize()

      // 监听窗口大小变化，调整图表大小
      window.addEventListener('resize', () => {
        if (chart) {
          chart.resize()
        }
      })

      logger.info('图表渲染完成')
      ElMessage.success('图表渲染完成')
      } catch (error) {
        // 渲染失败时，重置渲染标志
        chartRendered.value = false
        logger.error('图表渲染失败', error)
        ElMessage.error(`图表渲染失败: ${error.message}`)
      }
    }

    const exportChart = (type = 'png') => {
      if (!chart) {
        ElMessage.warning('请先生成图表')
        return
      }

      try {
        // 获取当前选中的课程和班级
        const selectedCourse = courses.value.find(c => c.id === filterForm.value.courseId)
        const selectedClass = filteredClasses.value.find(c => c.id === filterForm.value.classId)

        if (!selectedCourse || !selectedClass) {
          ElMessage.warning('请先选择课程和班级')
          return
        }

        // 获取图表的base64编码
        const dataURL = chart.getDataURL({
          type: type === 'jpeg' ? 'jpeg' : 'png',
          pixelRatio: 2,
          backgroundColor: '#fff'
        })

        // 构建文件名：课程名_班级名_实验报告提交率分析
        const fileName = `${selectedCourse.name}_${selectedClass.name}_实验报告提交率分析.${type === 'jpeg' ? 'jpg' : type}`

        // 创建下载链接
        const link = document.createElement('a')
        link.download = fileName
        link.href = dataURL
        document.body.appendChild(link)
        link.click()
        document.body.removeChild(link)

        logger.info(`图表导出为${type.toUpperCase()}成功`, { fileName })
        ElMessage.success(`图表导出为${type.toUpperCase()}成功`)
      } catch (error) {
        logger.error('图表导出失败', error)
        ElMessage.error('图表导出失败')
      }
    }

    const handleExportCommand = (command) => {
      if (command === 'pdf') {
        exportToPDF()
      } else if (command === 'svg') {
        exportToSVG()
      } else {
        exportChart(command)
      }
    }

    const exportToSVG = () => {
      if (!chart) {
        ElMessage.warning('请先生成图表')
        return
      }

      try {
        // 获取当前选中的课程和班级
        const selectedCourse = courses.value.find(c => c.id === filterForm.value.courseId)
        const selectedClass = filteredClasses.value.find(c => c.id === filterForm.value.classId)

        if (!selectedCourse || !selectedClass) {
          ElMessage.warning('请先选择课程和班级')
          return
        }

        // 获取SVG字符串
        const svgString = chart.getDataURL({
          type: 'svg',
          pixelRatio: 2,
          backgroundColor: '#fff'
        })

        // 创建Blob对象
        const blob = new Blob([svgString], { type: 'image/svg+xml' })

        // 构建文件名：课程名_班级名_实验报告提交率分析
        const fileName = `${selectedCourse.name}_${selectedClass.name}_实验报告提交率分析.svg`

        // 使用file-saver保存文件
        saveAs(blob, fileName)

        logger.info('图表导出为SVG成功', { fileName })
        ElMessage.success('图表导出为SVG成功')
      } catch (error) {
        logger.error('图表导出为SVG失败', error)
        ElMessage.error('图表导出为SVG失败')
      }
    }

    const exportToPDF = async () => {
      if (!chart) {
        ElMessage.warning('请先生成图表')
        return
      }

      try {
        // 获取当前选中的课程和班级
        const selectedCourse = courses.value.find(c => c.id === filterForm.value.courseId)
        const selectedClass = filteredClasses.value.find(c => c.id === filterForm.value.classId)

        if (!selectedCourse || !selectedClass) {
          ElMessage.warning('请先选择课程和班级')
          return
        }

        // 使用html2canvas将图表转换为canvas
        const canvas = await html2canvas(chartContainer.value, {
          backgroundColor: '#fff',
          scale: 2
        })

        // 创建PDF文档
        const pdf = new jsPDF({
          orientation: 'landscape',
          unit: 'mm',
          format: 'a4'
        })

        // 添加标题
        pdf.setFontSize(16)
        const title = `${selectedCourse.name} ${selectedClass.name} 实验报告提交率分析`
        pdf.text(title, pdf.internal.pageSize.getWidth() / 2, 15, { align: 'center' })

        // 添加图表
        const imgData = canvas.toDataURL('image/jpeg', 1.0)
        pdf.addImage(imgData, 'JPEG', 10, 30, pdf.internal.pageSize.getWidth() - 20, 100)

        // 添加数据表格
        if (chartData.value.length > 0) {
          pdf.addPage()
          pdf.setFontSize(16)
          pdf.text(`${selectedCourse.name} ${selectedClass.name} 实验报告提交率数据表`,
                  pdf.internal.pageSize.getWidth() / 2, 15, { align: 'center' })

          // 表格头
          pdf.setFontSize(12)
          pdf.setTextColor(0, 0, 0)
          pdf.text('实验名称', 20, 30)
          pdf.text('提交率', 80, 30)
          pdf.text('已交人数', 120, 30)
          pdf.text('总人数', 160, 30)

          // 表格内容
          pdf.setFontSize(10)
          chartData.value.forEach((item, index) => {
            const y = 40 + index * 10
            pdf.text(item.experimentName, 20, y)
            pdf.text(`${(item.submissionRate * 100).toFixed(2)}%`, 80, y)
            pdf.text(item.submittedCount.toString(), 120, y)
            pdf.text(item.totalStudents.toString(), 160, y)
          })
        }

        // 构建文件名：课程名_班级名_实验报告提交率分析
        const fileName = `${selectedCourse.name}_${selectedClass.name}_实验报告提交率分析.pdf`

        // 保存PDF
        pdf.save(fileName)

        logger.info('图表导出为PDF成功', { fileName })
        ElMessage.success('图表导出为PDF成功')
      } catch (error) {
        logger.error('图表导出为PDF失败', error)
        ElMessage.error('图表导出为PDF失败')
      }
    }

    const toggleDataTable = () => {
      showDataTable.value = !showDataTable.value
    }

    const refreshChart = async () => {
      if (experimentResults.value.length > 0) {
        try {
          await renderChart()
          ElMessage.success('图表已刷新')
        } catch (error) {
          logger.error('刷新图表失败', error)
          ElMessage.error(`刷新图表失败: ${error.message}`)
        }
      } else {
        ElMessage.warning('没有数据可供刷新')
      }
    }

    const onChartTypeChange = async () => {
      if (chartRendered.value && experimentResults.value.length > 0) {
        try {
          await renderChart()
          ElMessage.success(`已切换为${getChartTypeName(chartType.value)}`)
        } catch (error) {
          logger.error('切换图表类型失败', error)
          ElMessage.error(`切换图表类型失败: ${error.message}`)
        }
      }
    }

    const onColorChange = async () => {
      if (chartRendered.value && experimentResults.value.length > 0) {
        try {
          await renderChart()
          ElMessage.success('图表颜色已更新')
        } catch (error) {
          logger.error('更新图表颜色失败', error)
          ElMessage.error(`更新图表颜色失败: ${error.message}`)
        }
      }
    }

    const onLineStyleChange = async () => {
      if (chartRendered.value && experimentResults.value.length > 0) {
        try {
          await renderChart()
          ElMessage.success(`已切换为${lineStyle.value === 'smooth' ? '平滑曲线' : '直线'}样式`)
        } catch (error) {
          logger.error('更新折线样式失败', error)
          ElMessage.error(`更新折线样式失败: ${error.message}`)
        }
      }
    }

    const getChartTypeName = (type) => {
      const typeMap = {
        'line': '折线图',
        'bar': '柱状图',
        'pie': '饼图',
        'radar': '雷达图'
      }
      return typeMap[type] || type
    }

    // 生命周期钩子
    onMounted(() => {
      loadData()
    })

    return {
      filterForm,
      analyzing,
      chartContainer,
      chartRendered,
      courses,
      filteredClasses,
      chartType,
      chartColor,
      lineStyle,
      showDataTable,
      chartData,
      showDirectorySelector,
      handleCourseChange,
      handleSelectDirectory,
      handleDirectorySelected,
      analyzeReports,
      exportChart,
      handleExportCommand,
      toggleDataTable,
      refreshChart,
      onChartTypeChange,
      onColorChange,
      onLineStyleChange
    }
  }
}
</script>

<style scoped>
.visualization-container {
  max-width: 1200px;
  margin: 0 auto;
}

.filter-card {
  margin-bottom: 20px;
}

.chart-card {
  margin-bottom: 20px;
}

.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.card-header h2, .card-header h3 {
  margin: 0;
  color: #303133;
}

.filter-form {
  margin-top: 20px;
}

.chart-area {
  position: relative;
  width: 100%;
  min-height: 500px;
}

.chart-container {
  width: 100%;
  height: 500px;
  z-index: 1;
}

.chart-actions {
  display: flex;
  align-items: center;
}

.data-table-container {
  margin-top: 20px;
  padding-top: 20px;
  border-top: 1px solid #ebeef5;
}

.data-table-container h4 {
  margin-top: 0;
  margin-bottom: 15px;
  color: #303133;
  font-size: 16px;
}

.chart-placeholder {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 2;
  background-color: #f5f7fa;
}

.empty-icon {
  font-size: 60px;
  color: #909399;
}
</style>
